package hotel.quartz.oversea.job.switchs;

import com.alibaba.fastjson.JSON;
import hotel.base.oversea.constant.CommonConstants;
import hotel.base.oversea.constant.CommonUrlConstants;
import hotel.base.oversea.constant.quartz.UrlSwitchsEnums;
import hotel.base.oversea.utils.DateUtil;
import hotel.base.oversea.utils.GsonUtils;
import hotel.base.oversea.utils.JacksonUtil;
import hotel.base.oversea.utils.Result;
import hotel.quartz.oversea.config.service.RedisService;
import hotel.quartz.oversea.job.base.BaseJob;
import hotel.quartz.oversea.util.JobRestTemplateUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <H1></H1>
 *
 * @author HuangT
 * @date 2020/7/2 17:35
 */
@Slf4j
@Service
public class SwitchSaleRoomExpireUpdatePriceJob implements BaseJob {

    private final String timestamp = "Ssreupj" + System.currentTimeMillis();
    private final String redisKeyCanPushRoomPageIndex = "quartz_switch_can_push_room_page_index";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RedisService redisService;

    /**
     * （不停止，一直跑定时器）
     * 更新即将过期的售卖房型为最新有效价格
     * 涉及接口：1、携程外放接口 分页返回需更新价格的售卖房型ids（switchs_create_room）
     * 2、推送价格更新接口（一次一个售卖房型id）
     * 定时器时间： 一分钟一次，每次调用接口(1),循环ids，sleep一秒，每秒调用三次接口(2)
     * 接口(2)价格推送比较特殊，该接口携程支持每秒最多9次
     * 业务描述：
     * 房型价格上架后，15天有效期，我们会在提前2天进行价格更新
     * 而价格的推送是有有效期的，价格推送 一次有效期为 15天；我们暂时约定为推送过一次后在有效期 14天期间不再推送，在提前15天时再次进行推送；
     *
     * @param jobExecutionContext
     */
    @Override
    @SneakyThrows
    public void execute(JobExecutionContext jobExecutionContext) {
        log.info("Switch Sale Room Expire Update Price Job {} >>>>>>>> 携程过期前更新房型价格定时器执行时间: {}", timestamp, DateUtil.getNowTime());
        // 请求接口1，获取需要更新价格的房型ids
        //从redis获取page值
        Integer page = (Integer)redisService.get(redisKeyCanPushRoomPageIndex);
        if (null == page || page == 0||page>100) {
            page = 1;
            redisService.remove(redisKeyCanPushRoomPageIndex);
        }
        log.info("Switch Sale Room Expire Update Price Job 携程过期前更新房型价格定时器 page:{}", page);
     //   String getCanPushRoomIdListUrl = CommonUrlConstants.SWITCHS_HOST + UrlSwitchsEnums.canPushRoom.GET.getValue();
        String getCanPushRoomIdListUrl = CommonUrlConstants.SWITCHS_ONLINE_HOST + UrlSwitchsEnums.canPushRoom.GET.getValue();
        Result response = getCanPushRoomIdList(getCanPushRoomIdListUrl, page);
        if (null == response) {
            log.info("Switch Sale Room Expire Update Price Job 携程过期前更新房型价格定时器 response null");
            redisService.set(redisKeyCanPushRoomPageIndex,0);
            return;
        }
        if(response.getCode()!= CommonConstants.SUCCESS){
           return;
        }
        Map<Integer,Object> map= (Map<Integer, Object>) JSON.parse(JacksonUtil.objectToJson(response));
        Object dataIds = response.getData();
        log.info("Switch Sale Room Expire Update Price Job 携程过期前更新房型价格定时器 dataIds:{}", dataIds);
        if (null == dataIds) {
            log.info("Switch Sale Room Expire Update Price Job 携程过期前更新房型价格定时器 暂无需要更新价格的房型");
            if(redisService.exists(redisKeyCanPushRoomPageIndex)){
                redisService.remove(redisKeyCanPushRoomPageIndex);
            }
            return;
        }
        if (null == map) {
            log.info("Switch Sale Room Expire Update Price Job 携程过期前更新房型价格定时器 暂无需要更新价格的房型");
            if(redisService.exists(redisKeyCanPushRoomPageIndex)){
                redisService.remove(redisKeyCanPushRoomPageIndex);
            }
            return;
        }
        log.info("============解析成Map为{}=====", JacksonUtil.objectToJson(map));
       /* int dataSize = ((JSONObject)dataIds).size();*/
        int dataSize=map.size();
        //接口1有正确返回数据时，继续请求第二个接口
        if (dataSize > 0) {
            log.info("Switch Sale Room Expire Update Price Job 携程过期前更新房型价格定时器 存在需推送价格");
            // 请求接口2，推送价格
            String pushRoomDataUrl = CommonUrlConstants.SWITCHS_HOST + UrlSwitchsEnums.canPushRoom.PUSH.getValue();
            Result result = pushRoomData(pushRoomDataUrl, dataIds);
            if (result.getCode() == CommonConstants.SUCCESS) {
               redisService.set(redisKeyCanPushRoomPageIndex, page + 1);
            }
        } else {
            //如果第1个接口返回数据，且请求成功，则下次定时器重新从第1页开始查询
            redisService.remove(redisKeyCanPushRoomPageIndex);
        }

        log.info("Switch Sale Room Expire Update Price Job >>>>>>>> 携程过期前更新房型价格定时器结束时间: {},{}", timestamp, new Date());
    }

    /**
     * <H1>售卖房型价格更新推送</H1>
     *
     * @param pushRoomDataUrl
     * @param data
     * @return hotel.base.oversea.utils.Result
     * @author HuangT
     * @date 2020/7/2 14:56
     */
    private Result pushRoomData(String pushRoomDataUrl, Object data) {
        log.info("Switch Sale Room Expire Update Price Job 携程过期前更新房型价格定时器 进入pushRoomData，遍历循环推送:{},{}", pushRoomDataUrl, JSON.toJSONString(data));
        //转换data为map
        String jsonStr = GsonUtils.GsonString(data);
        Map<String, Integer> map = GsonUtils.IntegerToMaps(jsonStr);
        //遍历map，并封装请求参数
        log.info("Switch Sale Room Expire Update Price Job 携程过期前更新房型价格定时器 进入pushRoomData，遍历循环推送size为:{}", map.size());
        int s = 0;
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            //组装请求参数
            Map<String, Integer> paramMap = new HashMap<>();
            paramMap.put("hotelId", entry.getValue());
            paramMap.put("roomId", Integer.valueOf(entry.getKey()));
            //如果一个房型一天都在重复出现，说明应该重新推，可能是查无价格的房型会影响
            if(redisService.exists("push_today_room_id"+Integer.valueOf(entry.getKey()))){
                redisService.remove(redisKeyCanPushRoomPageIndex);
            }
            //发起请求
            Result response = JobRestTemplateUtils.post(pushRoomDataUrl, JSON.toJSONString(paramMap), restTemplate);
            if (response.getCode() != CommonConstants.SUCCESS) {
                log.error("Switch Sale Room Expire Update Price Job {} 售卖房型推送 pushRoomData 发起请求 当前次推送返回失败 : {},{},{}", timestamp, pushRoomDataUrl, JSON.toJSONString(paramMap), JSON.toJSONString(response));
            } else {
                redisService.set("push_today_room_id"+Integer.valueOf(entry.getKey()),"1",(long)500);
                s += 1;
            }
            if(null != redisTemplate.opsForValue().get("job_pushRoomData_stop")){
                break;
            }
        }
        log.info("Switch Sale Room Expire Update Price Job 携程过期前更新房型价格定时器 进入pushRoomData，遍历循环推送结束{}，成功个数为：{},实际需推送：{}", DateUtil.getNowTime(), s, map.size());
        return new Result<>();
    }

    /**
     * <H1>获取能推送价格的房型id列表</H1>
     *
     * @param getCanPushRoomIdListUrl
     * @return hotel.base.oversea.utils.Result
     * @author HuangT
     * @date 2020/7/2 14:32
     */
    private Result getCanPushRoomIdList(String getCanPushRoomIdListUrl, Integer page) {
        Map<String, Object> map = new HashMap<>();
        map.put("page", page);
        //发起请求
        Result response = JobRestTemplateUtils.get(getCanPushRoomIdListUrl, map, restTemplate);
        return response;
    }

}
